#pragma once

#include "Vectors.hpp"
#include "Ray.hpp"
#include <boost/optional.hpp>

namespace cge {
	class Plane {
	public:
		Plane( double a, double b, double c, double d ): abc_(a,b,c), d_(d) { renormalize(); }
		Plane( const vec3 &normal, double d ): abc_(normal), d_(d) { renormalize(); }

		double signedDistance( const vec3 &p ) { return abc_.dot(p) + d_; }
		double distance( const vec3 &p ) { return abs(signedDistance(p)); }

		boost::optional<vec3> intersect( const Ray &r ) {
			boost::optional<vec3> ret;
			double proj = abc_.dot(r.getDirection());
			if( proj == 0 )
				return ret;
			else
				return r.pointAt( -signedDistance(r.getPoint()) / proj );
		}

		const vec3& getNormal() { return abc_; }
		double      getD() { return d_; }

	private:
		void renormalize() {
			double n_ = abc_.norm();
			assert( n_ > 0.0 );
			abc_ /= n;
			d_ /= n;
		}

		vec3   abc_;
		double d_;
	};
}